package com.pokermind.dse.tcp.server;

import com.pokermind.dse.tcp.config.TcpServerConfig;
import com.pokermind.dse.tcp.protocol.ProtocolDecoder;
import com.pokermind.dse.tcp.protocol.ProtocolEncoder;
import com.pokermind.dse.tcp.handler.ServerChannelInitializer;
import io.micrometer.core.instrument.MeterRegistry;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.ResourceLeakDetector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Netty TCP Server
 * 高性能TCP服务器，基于Netty实现
 * 
 * 核心特性：
 * 1. 支持Epoll（Linux）和NIO（跨平台）
 * 2. 可配置的线程模型
 * 3. 完整的连接管理和监控
 * 4. 优雅关闭支持
 * 5. 内存泄漏检测
 * 
 * @author PokerMind Team
 */
@Component
public class NettyTcpServer {

    private static final Logger logger = LoggerFactory.getLogger(NettyTcpServer.class);

    @Autowired
    private TcpServerConfig config;

    @Autowired
    private MeterRegistry meterRegistry;

    @Autowired
    private ServerChannelInitializer channelInitializer;

    // Netty组件
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private Channel serverChannel;
    private ServerBootstrap bootstrap;
    
    // 服务器状态
    private volatile boolean running = false;
    private final CountDownLatch shutdownLatch = new CountDownLatch(1);

    @PostConstruct
    public void initialize() {
        configureNettySettings();
        setupBootstrap();
        logger.info("NettyTcpServer initialized with config: {}", config.getConfigSummary());
    }

    /**
     * 启动服务器
     */
    public void start() {
        if (running) {
            logger.warn("TCP Server is already running");
            return;
        }

        try {
            logger.info("Starting TCP Server on {}:{}", config.getServer().getHost(), config.getServer().getPort());

            ChannelFuture future = bootstrap.bind(config.getServer().getHost(), config.getServer().getPort()).sync();
            serverChannel = future.channel();
            
            if (future.isSuccess()) {
                running = true;
                logger.info("TCP Server started successfully on {}:{}", 
                        config.getServer().getHost(), config.getServer().getPort());
                
                // 注册监控指标
                registerMetrics();
                
                // 异步等待服务器关闭
                startShutdownWaiter();
                
            } else {
                logger.error("Failed to start TCP Server: {}", future.cause().getMessage());
                throw new RuntimeException("TCP Server startup failed", future.cause());
            }
            
        } catch (Exception e) {
            logger.error("Error starting TCP Server: {}", e.getMessage(), e);
            shutdown();
            throw new RuntimeException("TCP Server startup failed", e);
        }
    }

    /**
     * 优雅关闭服务器
     */
    @PreDestroy
    public void shutdown() {
        if (!running) {
            logger.info("TCP Server is already stopped");
            return;
        }

        logger.info("Shutting down TCP Server gracefully...");
        running = false;

        try {
            // 关闭服务器通道
            if (serverChannel != null) {
                serverChannel.close().await(10, TimeUnit.SECONDS);
            }

            // 关闭线程池
            if (bossGroup != null) {
                bossGroup.shutdownGracefully(2, 10, TimeUnit.SECONDS).await();
            }
            if (workerGroup != null) {
                workerGroup.shutdownGracefully(2, 15, TimeUnit.SECONDS).await();
            }

            shutdownLatch.countDown();
            logger.info("TCP Server shutdown completed");

        } catch (Exception e) {
            logger.error("Error during TCP Server shutdown: {}", e.getMessage(), e);
        }
    }

    /**
     * 检查服务器是否正在运行
     */
    public boolean isRunning() {
        return running && serverChannel != null && serverChannel.isActive();
    }

    /**
     * 等待服务器关闭
     */
    public void awaitShutdown() throws InterruptedException {
        shutdownLatch.await();
    }

    /**
     * 配置Netty设置
     */
    private void configureNettySettings() {
        // 设置内存泄漏检测级别
        ResourceLeakDetector.Level leakLevel = ResourceLeakDetector.Level.valueOf(
                config.getPerformance().getLeakDetection().toUpperCase());
        ResourceLeakDetector.setLevel(leakLevel);
        
        logger.info("Netty settings configured - leakDetection: {}, epoll: {}", 
                leakLevel, config.canUseEpoll());
    }

    /**
     * 设置ServerBootstrap
     */
    private void setupBootstrap() {
        // 选择EventLoopGroup实现
        if (config.canUseEpoll()) {
            bossGroup = new EpollEventLoopGroup(config.getServer().getBossThreads());
            workerGroup = new EpollEventLoopGroup(config.getActualWorkerThreads());
            logger.info("Using Epoll transport - boss: {}, worker: {}", 
                    config.getServer().getBossThreads(), config.getActualWorkerThreads());
        } else {
            bossGroup = new NioEventLoopGroup(config.getServer().getBossThreads());
            workerGroup = new NioEventLoopGroup(config.getActualWorkerThreads());
            logger.info("Using NIO transport - boss: {}, worker: {}", 
                    config.getServer().getBossThreads(), config.getActualWorkerThreads());
        }

        bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup)
                .channel(config.canUseEpoll() ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(channelInitializer)
                .option(ChannelOption.SO_BACKLOG, config.getServer().getSoBacklog())
                .option(ChannelOption.SO_REUSEADDR, config.getServer().isSoReuseaddr())
                .childOption(ChannelOption.SO_KEEPALIVE, config.getServer().isSoKeepalive())
                .childOption(ChannelOption.TCP_NODELAY, config.getServer().isTcpNodelay())
                .childOption(ChannelOption.SO_RCVBUF, 64 * 1024)
                .childOption(ChannelOption.SO_SNDBUF, 64 * 1024)
                .childOption(ChannelOption.ALLOCATOR, 
                        "pooled".equals(config.getPerformance().getAllocatorType()) ? 
                        io.netty.buffer.PooledByteBufAllocator.DEFAULT : 
                        io.netty.buffer.UnpooledByteBufAllocator.DEFAULT);
    }

    /**
     * 异步等待服务器关闭
     */
    private void startShutdownWaiter() {
        Thread shutdownWaiter = new Thread(() -> {
            try {
                if (serverChannel != null) {
                    serverChannel.closeFuture().await();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                logger.warn("Shutdown waiter interrupted");
            } finally {
                shutdown();
            }
        }, "tcp-shutdown-waiter");
        
        shutdownWaiter.setDaemon(true);
        shutdownWaiter.start();
    }

    /**
     * 注册监控指标
     */
    private void registerMetrics() {
        // 注册服务器状态指标
        meterRegistry.gauge("tcp.server.running", this, server -> server.isRunning() ? 1 : 0);
        meterRegistry.gauge("tcp.server.boss.threads", config.getServer().getBossThreads());
        meterRegistry.gauge("tcp.server.worker.threads", config.getActualWorkerThreads());
        
        logger.debug("TCP Server metrics registered");
    }

    /**
     * 获取服务器信息
     */
    public String getServerInfo() {
        return String.format(
                "NettyTcpServer{running=%s, host=%s, port=%d, bossThreads=%d, workerThreads=%d, transport=%s}",
                running,
                config.getServer().getHost(),
                config.getServer().getPort(),
                config.getServer().getBossThreads(),
                config.getActualWorkerThreads(),
                config.canUseEpoll() ? "epoll" : "nio"
        );
    }
}
